// This is the main DLL file.

#include "stdafx.h"
#include "GripGpu.h"

using namespace System::Runtime::InteropServices;

// CUDA Kernels
extern "C" cudaError_t CUDA_AlignColorFrame(unsigned char* src, unsigned char* dst, int length);
extern "C" cudaError_t CUDA_BackgroundSubtract(unsigned char* depthFrame, unsigned char* alphaChannel, int length, int playerIndex);
extern "C" cudaError_t CUDA_SetMapIndices(int* mapIndices);
extern "C" cudaError_t CUDA_YUVtoBGRA(unsigned char* src, unsigned char* dst, int width, int height);

namespace GRIP
{
	namespace Cuda
	{
		void GripGpu::AlignColorFrame(CudaDeviceBuffer^ Source, CudaDeviceBuffer^ Dest)
		{
			CudaErrorCheck(CUDA_AlignColorFrame(Source->Ptr(), Dest->Ptr(), Source->BufferSize() / 4));
		};

		void GripGpu::BackgroundSubtract(CudaDeviceBuffer^ DepthFrame, int PlayerIndex)
		{
			CudaErrorCheck(CUDA_BackgroundSubtract(DepthFrame->Ptr(), NULL, DepthFrame->BufferSize() / 2, PlayerIndex));
		};

		void GripGpu::BackgroundSubtract(CudaDeviceBuffer^ DepthFrame, CudaDeviceBuffer^ AlphaChannel, int PlayerIndex)
		{
			CudaErrorCheck(CUDA_BackgroundSubtract(DepthFrame->Ptr(), AlphaChannel->Ptr(), AlphaChannel->BufferSize(), PlayerIndex));
		};

		generic<typename T>
		void GripGpu::SetMapIndices(array<T>^ Source)
		{
			GCHandle handle = GCHandle::Alloc(Source, GCHandleType::Pinned);
			int size = Source->Length *sizeof(T);
			int* MapIndices;
			CudaErrorCheck(cudaMalloc((void**) &MapIndices, size));
			CudaErrorCheck(cudaMemcpy(MapIndices, (void*)handle.AddrOfPinnedObject(), size, cudaMemcpyHostToDevice));
			handle.Free();
			CudaErrorCheck(CUDA_SetMapIndices(MapIndices));
		};

		void GripGpu::YuvToBgra(CudaDeviceBuffer^ Source, CudaDeviceBuffer^ Target)
		{
			CudaErrorCheck(CUDA_YUVtoBGRA(Source->Ptr(), Target->Ptr(), Source->GetWidth(), Source->GetHeight()));
		};
	}
}